#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Room_1专用实时传感器数据生成器
每5秒使用预测模型生成一次新的传感器数据
"""

import pandas as pd
import numpy as np
import os
import sys
import time
import threading
import warnings
import json
from datetime import datetime, timedelta

# 添加项目根目录到路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

warnings.filterwarnings('ignore')

class RealtimeDataGeneratorRoom1:
    """Room_1实时传感器数据生成器"""
    
    def __init__(self, output_file='C:/python/auto_room/data/Room_1/realtime_sensor_data.csv', max_records=1000):
        """
        初始化生成器
        
        参数:
        output_file: 输出CSV文件路径
        max_records: 最大保留记录数
        """
        self.room_id = "Room_1"
        self.output_file = output_file
        self.json_file = output_file.replace('.csv', '.json')
        self.max_records = max_records
        self.is_running = False
        
        # 传感器列定义
        self.sensor_columns = [
            'S1_Temp', 'S2_Temp', 'S3_Temp', 'S4_Temp',
            'S1_Light', 'S2_Light', 'S3_Light', 'S4_Light',
            'S1_Sound', 'S2_Sound', 'S3_Sound', 'S4_Sound',
            'S5_CO2', 'S5_CO2_Slope', 'S6_PIR', 'S7_PIR'
        ]
        
        # 种子数据
        self.seed_data = None
        self.window_size = 300  # 使用300条历史数据窗口以获得更稳定的预测
        
        # 确保输出目录存在
        os.makedirs(os.path.dirname(self.output_file), exist_ok=True)
        
    def load_seed_data(self):
        """加载种子数据（历史数据的最后300条）"""
        print(f"📊 [{self.room_id}] 加载种子数据...")
        
        # Room_1专用数据路径
        data_path = "data/Room_1/sensor_data.csv"
        
        if os.path.exists(data_path):
            try:
                df = pd.read_csv(data_path)
                print(f"✅ [{self.room_id}] 从 {data_path} 加载了 {len(df)} 条历史记录")
                
                # 确保有DateTime列
                if 'DateTime' not in df.columns:
                    df['DateTime'] = pd.to_datetime(
                        df['Date'] + ' ' + df['Time'], 
                        format='%d-%m-%Y %H:%M:%S'
                    )
                
                # 排序并取最后window_size条记录作为种子
                df = df.sort_values('DateTime').tail(self.window_size).reset_index(drop=True)
                
                # 检查所需列是否存在
                missing_cols = [col for col in self.sensor_columns if col not in df.columns]
                if missing_cols:
                    print(f"⚠️  [{self.room_id}] 缺少传感器列: {missing_cols}")
                    self.create_random_seed_data()
                    return
                
                self.seed_data = df
                print(f"✅ [{self.room_id}] 种子数据准备完成，共 {len(df)} 条记录")
                return
                
            except Exception as e:
                print(f"❌ [{self.room_id}] 读取 {data_path} 失败: {e}")
        
        # 如果数据文件无法加载，创建随机种子数据
        print(f"⚠️  [{self.room_id}] 无法加载历史数据，创建随机种子数据...")
        self.create_random_seed_data()
    
    def create_random_seed_data(self):
        """创建随机种子数据"""
        print(f"🎲 [{self.room_id}] 创建随机种子数据...")
        
        # 生成时间序列（从30分钟前开始，每30秒一条）
        end_time = datetime.now()
        start_time = end_time - timedelta(seconds=30 * self.window_size)
        
        timestamps = []
        current_time = start_time
        for i in range(self.window_size):
            timestamps.append(current_time)
            current_time += timedelta(seconds=30)
        
        data = []
        for timestamp in timestamps:
            row = {
                'Date': timestamp.strftime('%d-%m-%Y'),
                'Time': timestamp.strftime('%H:%M:%S'),
                'DateTime': timestamp,
                # 温度传感器：20-30°C 的合理范围
                'S1_Temp': np.random.normal(25, 2),
                'S2_Temp': np.random.normal(24.5, 1.5),
                'S3_Temp': np.random.normal(24.8, 1.8),
                'S4_Temp': np.random.normal(25.2, 2.2),
                # 光线传感器：30-200的范围
                'S1_Light': np.random.randint(30, 200),
                'S2_Light': np.random.randint(25, 150),
                'S3_Light': np.random.randint(40, 180),
                'S4_Light': np.random.randint(35, 160),
                # 声音传感器：0-0.5的范围
                'S1_Sound': np.random.uniform(0, 0.5),
                'S2_Sound': np.random.uniform(0, 0.3),
                'S3_Sound': np.random.uniform(0, 0.4),
                'S4_Sound': np.random.uniform(0, 0.6),
                # CO2传感器：350-600 ppm
                'S5_CO2': np.random.normal(450, 50),
                'S5_CO2_Slope': np.random.normal(0, 1),
                # PIR传感器：0或1
                'S6_PIR': np.random.choice([0, 1], p=[0.8, 0.2]),
                'S7_PIR': np.random.choice([0, 1], p=[0.85, 0.15])
            }
            data.append(row)
        
        self.seed_data = pd.DataFrame(data)
        print(f"✅ [{self.room_id}] 随机种子数据创建完成，共 {len(self.seed_data)} 条")
    
    def generate_trend_based_data(self, current_data):
        """基于趋势生成下一个数据点"""
        if len(current_data) < 2:
            # 如果数据不足，使用最后一条数据加随机变化
            last_row = current_data.iloc[-1] if len(current_data) > 0 else self.seed_data.iloc[-1]
            return np.array([
                last_row['S1_Temp'] + np.random.normal(0, 0.1),
                last_row['S2_Temp'] + np.random.normal(0, 0.1),
                last_row['S3_Temp'] + np.random.normal(0, 0.1),
                last_row['S4_Temp'] + np.random.normal(0, 0.1),
                last_row['S1_Light'] + np.random.normal(0, 5),
                last_row['S2_Light'] + np.random.normal(0, 5),
                last_row['S3_Light'] + np.random.normal(0, 5),
                last_row['S4_Light'] + np.random.normal(0, 5),
                last_row['S1_Sound'] + np.random.normal(0, 0.02),
                last_row['S2_Sound'] + np.random.normal(0, 0.02),
                last_row['S3_Sound'] + np.random.normal(0, 0.02),
                last_row['S4_Sound'] + np.random.normal(0, 0.02),
                last_row['S5_CO2'] + np.random.normal(0, 2),
                last_row['S5_CO2_Slope'] + np.random.normal(0, 0.1),
                np.random.choice([0, 1], p=[0.8, 0.2]),  # S6_PIR
                np.random.choice([0, 1], p=[0.85, 0.15])  # S7_PIR
            ])
        
        # 计算简单趋势
        last_row = current_data.iloc[-1]
        prev_row = current_data.iloc[-2]
        
        prediction = []
        for col in self.sensor_columns:
            if 'PIR' in col:
                # PIR传感器随机生成
                prediction.append(np.random.choice([0, 1], p=[0.8, 0.2]))
            else:
                # 其他传感器基于趋势
                trend = (last_row[col] - prev_row[col]) * 0.5  # 缓和趋势
                noise_scale = 0.1 if 'Temp' in col else (5 if 'Light' in col else 0.02)
                new_value = last_row[col] + trend + np.random.normal(0, noise_scale)
                prediction.append(new_value)
        
        return np.array(prediction)
    
    def apply_sensor_constraints(self, prediction):
        """应用传感器数据约束"""
        # 温度传感器：15-35°C
        prediction[0:4] = np.clip(prediction[0:4], 15, 35)
        
        # 光线传感器：0-1000
        prediction[4:8] = np.clip(prediction[4:8], 0, 1000)
        
        # 声音传感器：0-2
        prediction[8:12] = np.clip(prediction[8:12], 0, 2)
        
        # CO2传感器：300-1000 ppm
        prediction[12] = np.clip(prediction[12], 300, 1000)
        
        # CO2斜率：-50到50
        prediction[13] = np.clip(prediction[13], -50, 50)
        
        # PIR传感器：0或1
        prediction[14:16] = np.round(np.clip(prediction[14:16], 0, 1)).astype(int)
        
        return prediction
    
    def generate_next_record(self, current_data):
        """生成下一条记录"""
        # 获取下一个时间点
        last_datetime = current_data['DateTime'].iloc[-1]
        next_datetime = last_datetime + timedelta(seconds=30)
        
        # 预测传感器数据
        prediction = self.generate_trend_based_data(current_data)
        prediction = self.apply_sensor_constraints(prediction)
        
        # 构建新记录
        new_record = {
            'Date': next_datetime.strftime('%d-%m-%Y'),
            'Time': next_datetime.strftime('%H:%M:%S'),
            'DateTime': next_datetime
        }
        
        # 添加传感器数据（保留适当的小数位数）
        for i, col in enumerate(self.sensor_columns):
            if 'PIR' in col:
                new_record[col] = int(prediction[i])
            elif 'Temp' in col:
                new_record[col] = round(float(prediction[i]), 2)
            elif 'Light' in col:
                new_record[col] = int(round(float(prediction[i])))
            else:
                new_record[col] = round(float(prediction[i]), 3)
        
        return new_record
    
    def save_to_csv(self, data):
        """保存数据到CSV文件"""
        try:
            # 准备保存的数据（去掉DateTime列）
            save_data = data.drop(columns=['DateTime'], errors='ignore').copy()
            
            # 控制文件大小，只保留最近的记录
            if len(save_data) > self.max_records:
                save_data = save_data.tail(self.max_records)
            
            save_data.to_csv(self.output_file, index=False)
            
        except Exception as e:
            print(f"❌ [{self.room_id}] 保存CSV文件失败: {e}")
    
    def save_latest_to_json(self, latest_record):
        """额外保存最新的一条记录到JSON文件"""
        if latest_record is None:
            return
            
        try:
            # 构建JSON数据结构
            json_data = {
                "room_id": self.room_id,
                "timestamp": datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                "data": {
                    "Date": latest_record['Date'],
                    "Time": latest_record['Time'],
                    "sensors": {
                        "temperature": {
                            "S1_Temp": float(latest_record['S1_Temp']),
                            "S2_Temp": float(latest_record['S2_Temp']),
                            "S3_Temp": float(latest_record['S3_Temp']),
                            "S4_Temp": float(latest_record['S4_Temp'])
                        },
                        "light": {
                            "S1_Light": int(latest_record['S1_Light']),
                            "S2_Light": int(latest_record['S2_Light']),
                            "S3_Light": int(latest_record['S3_Light']),
                            "S4_Light": int(latest_record['S4_Light'])
                        },
                        "sound": {
                            "S1_Sound": float(latest_record['S1_Sound']),
                            "S2_Sound": float(latest_record['S2_Sound']),
                            "S3_Sound": float(latest_record['S3_Sound']),
                            "S4_Sound": float(latest_record['S4_Sound'])
                        },
                        "environment": {
                            "S5_CO2": float(latest_record['S5_CO2']),
                            "S5_CO2_Slope": float(latest_record['S5_CO2_Slope']),
                            "S6_PIR": int(latest_record['S6_PIR']),
                            "S7_PIR": int(latest_record['S7_PIR'])
                        }
                    },
                    "summary": {
                        "avg_temperature": float((latest_record['S1_Temp'] + latest_record['S2_Temp'] + 
                                                 latest_record['S3_Temp'] + latest_record['S4_Temp']) / 4),
                        "avg_light": float((latest_record['S1_Light'] + latest_record['S2_Light'] + 
                                           latest_record['S3_Light'] + latest_record['S4_Light']) / 4),
                        "avg_sound": float((latest_record['S1_Sound'] + latest_record['S2_Sound'] + 
                                           latest_record['S3_Sound'] + latest_record['S4_Sound']) / 4),
                        "motion_detected": bool(latest_record['S6_PIR'] or latest_record['S7_PIR']),
                        "co2_level": float(latest_record['S5_CO2']),
                        "co2_trend": "increasing" if latest_record['S5_CO2_Slope'] > 0.1 else 
                                    ("decreasing" if latest_record['S5_CO2_Slope'] < -0.1 else "stable")
                    }
                },
                "status": "active",
                "generated_at": datetime.now().isoformat()
            }
            
            # 直接覆盖写入JSON文件
            with open(self.json_file, 'w', encoding='utf-8') as f:
                json.dump(json_data, f, ensure_ascii=False, indent=2)
                
        except Exception as e:
            print(f"❌ [{self.room_id}] 保存JSON文件失败: {e}")
    
    def data_generation_loop(self):
        """数据生成主循环"""
        print(f"🔄 [{self.room_id}] 启动数据生成循环...")
        
        # 初始化当前数据为种子数据
        current_data = self.seed_data.copy()
        
        # 保存初始种子数据
        self.save_to_csv(current_data)
        # 额外保存最后一条数据到JSON
        self.save_latest_to_json(current_data.iloc[-1].to_dict())
        print(f"💾 [{self.room_id}] 初始数据已保存到 {self.output_file}")
        
        generation_count = 0
        
        while self.is_running:
            try:
                # 生成下一条记录
                new_record = self.generate_next_record(current_data)
                
                # 添加到当前数据
                current_data = pd.concat([current_data, pd.DataFrame([new_record])], ignore_index=True)
                
                # 控制内存中的数据量
                if len(current_data) > self.window_size + 20:
                    current_data = current_data.tail(self.window_size + 10).reset_index(drop=True)
                
                # 保存到文件
                self.save_to_csv(current_data)
                
                # 额外保存最新数据到JSON文件
                self.save_latest_to_json(new_record)
                
                generation_count += 1
                
                # 打印状态
                if generation_count % 10 == 0:  # 每10次生成打印一次状态
                    print(f"📊 [{self.room_id}] 已生成 {generation_count} 条数据，最新时间: {new_record['DateTime']}")
                
                # 等待5秒
                time.sleep(5)
                
            except Exception as e:
                print(f"❌ [{self.room_id}] 数据生成出错: {e}")
                time.sleep(5)  # 出错后等待5秒再试
    
    def start(self):
        """启动数据生成器"""
        if self.is_running:
            print(f"⚠️  [{self.room_id}] 数据生成器已在运行中")
            return
        
        print(f"🚀 启动 {self.room_id} 实时传感器数据生成器")
        
        # 加载种子数据
        self.load_seed_data()
        
        if self.seed_data is None:
            print(f"❌ [{self.room_id}] 无法加载种子数据，启动失败")
            return
        
        # 设置运行标志
        self.is_running = True
        
        # 启动数据生成线程
        self.generation_thread = threading.Thread(target=self.data_generation_loop, daemon=True)
        self.generation_thread.start()
        
        print(f"✅ [{self.room_id}] 数据生成器已启动")
    
    def stop(self):
        """停止数据生成器"""
        if not self.is_running:
            print(f"⚠️  [{self.room_id}] 数据生成器未在运行")
            return
        
        print(f"🛑 [{self.room_id}] 正在停止数据生成器...")
        self.is_running = False
        
        # 等待线程结束
        if hasattr(self, 'generation_thread'):
            self.generation_thread.join(timeout=10)
        
        print(f"✅ [{self.room_id}] 数据生成器已停止")

def main():
    """主函数"""
    generator = RealtimeDataGeneratorRoom1()
    
    try:
        generator.start()
        
        # 保持主线程运行
        while True:
            time.sleep(1)
            
    except KeyboardInterrupt:
        print("\n⚠️  收到停止信号...")
        generator.stop()
        print("👋 程序已退出")

if __name__ == "__main__":
    main() 